package com.fanxing;

import java.util.ArrayList;
import java.util.List;
import java.util.Optional;

public class Test01 {

    /**
     * ? extends A 和 ? super A
     *   1.如果你想从一个数据类型中获取数据，使用 ? extends 通配符
     *   2.如果你想把对象写入一个数据结构里，使用 ? super 通配符
     *   3.如果你即想读取数据，又想操作数据，那么就别使用通配符
     *
     *   PECS法则：(Product Extends Consumer Super)
     * @param args
     */
    public static void main(String[] args) {

        List<Student> list1 = new ArrayList<>();
        list1.add(new Student());
        List<Person> list2 = new ArrayList<>();
        list2.add(new Person());
        List<Object> list3 = new ArrayList<>();
        list3.add(new Object());

        show1(list1);
        show1(list2);
        show1(list3);

        System.out.println("============");
        show2(list1);
        show2(list2);
        //show2(list3); 编译不通过 传递的集合的泛型要么是Person要么是Person的子类
        System.out.println("============");
        // show3(list1); 编译不通过 传递的集合的泛型要么是Person要么是Person的父类
        show3(list2);
        show3(list3);

    }

    /**
     * 泛型的通配符 ?
     * 可读，不可写
     * @param list
     */
    public static void show1(List<?> list){
        // 读取操作
        Object o = list.get(0);
        System.out.println("show1:" + list.get(0));
        // 写入操作 Student  Integer Double
        // list.add(new Object()); 在通配符 ? 下不允许写入数据，有一个特例
        list.add(null); // 添加null 可以，因为任意的引用类型我们都可以赋值null
    }

    /**
     * 通配符上限
     *   可读不可写
     * @param list
     */
    public static void show2(List<? extends Person> list){
        // 读取操作
        Person o = list.get(0);
        System.out.println("show2:" + list.get(0));
        // 写入数据
        // list.add(new Student()); 添加数据类型同样无法确定，所以不让添加 特例 null
        list.add(null);
    }

    /**
     * 泛型通配符 下限
     *    可读可写，写得类型必须是 指定的下限或其子类
     * @param list
     */
    public static void show3(List<? super Person> list){
        // 读取操作
        Object o = list.get(0);
        System.out.println("show3:" + list.get(0));
        // 写入操作 因为传递过来的list中的数据 要么是 Person 要么是 Person的父类
        // 那么我们在集合中添加的数据是 Person或者Person的子类， 这些数据肯定是 传递过来数据的相同类型或者子类，
        // 满足多态的情况
        list.add(new Student());
        list.add(new Person());
    }
}
